/***************************************************************************

Copyright (c) Microsoft Corporation. All rights reserved.
This code is licensed under the Visual Studio SDK license terms.
THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.

***************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Package;
using Babel.ParserGenerator;
using System.Text.RegularExpressions;

namespace Babel.Parser
{
    public class ElementInfo
    {
        public string ElementName;
        public int line;
        public ElementInfo(string name, LexLocation l)
        {
            ElementName = name;
            line = l.sLin;
        }
    }
	public partial class Parser
	{
		ParseRequest request;
        //matched braces that current velocity code contains
		IList<TextSpan[]> braces;
        //variable that current velocity code contains , members[0] is the variable self , members[1] is the  value of the member[0]
        IList<TextSpan[]> members;
        //matched markup that current umc code contains
        IList<TextSpan[]> markupMatch;
        //elements that current umc code contains , elements[0] is the elements self , elements[1]~elements[n] is the attribute that define in the elements[0]
        IList<ElementInfo> elements;

		public ParseRequest Request
		{
			get { return this.request; }
		}
        public IList<TextSpan[]> Braces
        {
            get { return this.braces; }
        }
        public IList<TextSpan[]> Members
        {
            get { return this.members; }
        }
        public IList<TextSpan[]> MarkupMatch
        {
            get { return this.markupMatch; }
        }
        public IList<ElementInfo> Elements
        {
            get { return this.elements; }
        }


        //init this parse , the requst contains sink
		public void MBWInit(ParseRequest request)
		{
			this.request = request;
			braces = new List<TextSpan[]>();
            members = new List<TextSpan[]>();
            markupMatch = new List<TextSpan[]>();
            elements = new List<ElementInfo>();
		}

        //internal void Match(LexLocation lh, LexLocation rh)
        //{
        //    DefineMatch(MkTSpan(lh), MkTSpan(rh));
        //}

        //only support 2 pairs matched braces 
        internal void MatchBrace(LexLocation lh, LexLocation rh)
        {
            braces.Add(new TextSpan[] { MkTSpan(lh), MkTSpan(rh) });
        }

        //add member first is the member self , second is the value of the member
        //internal void AddMember(LexLocation lh,LexLocation rh)
        //{
        //    members.Add(new TextSpan[] { MkTSpan(lh), MkTSpan(rh) });
        //}

        //add pairs markup
        internal void MatchMarkup(LexLocation lh, LexLocation rh)
        {
            markupMatch.Add(new TextSpan[] { MkTSpan(lh), MkTSpan(rh) });
        }

        //add element first is the element self
        internal void AddElement(string name,LexLocation rh)
        {
            elements.Add(new ElementInfo(name, rh));
        }

        internal TextSpan MkTSpan(LexLocation s) { return TextSpan(s.sLin, s.sCol, s.eLin, s.eCol); }


        ErrorHandler handler = null;
        public void SetHandler(ErrorHandler hdlr) { handler = hdlr; }
        internal void CallHdlr(string msg, LexLocation val)
        {
            handler.AddError(msg, val.sLin, val.sCol, val.eCol - val.sCol);
        }

        //// brace matching, pairs and triples
        //public void DefineMatch(int priority, params TextSpan[] locations)
        //{			
        //    if (locations.Length == 2)
        //        braces.Add(new TextSpan[] { locations[0], 
        //            locations[1]});

        //    else if (locations.Length >= 3)
        //        braces.Add(new TextSpan[] { locations[0], 
        //            locations[1],
        //            locations[2]});
        //}

        //public void DefineMatch(params TextSpan[] locations)
        //{
        //    DefineMatch(0, locations);
        //}

		public AuthoringSink Sink
		{
			get { return this.request.Sink; }
		}
		// hidden regions - not working?
		public void DefineRegion(TextSpan span)
		{
			Sink.AddHiddenRegion(span);
		}

		// auto hidden?
		// public void DefineHiddenRegion
		// etc. see NewHiddenRegion structure


		// error reporting
		public void ReportError(TextSpan span, string message, Severity severity)
		{
			Sink.AddError(request.FileName, message, span, severity);
		}


        /// <summary>
        /// 
        /// </summary>
        /// <param name="ts"></param>
        /// <param name="orignalName"></param>
        /// <returns></returns>
        private string GetWholeMethodName(TextSpan ts, string orignalName)
        {
            string ret = orignalName;
            try
            {
                string lineText;
                this.request.View.GetTextStream(ts.iStartLine, 0, ts.iEndLine, ts.iEndIndex, out lineText);
                lineText = lineText.Replace("{", "").Replace("}", "").Replace(" ", "");
                string IdetifierPattern = @"[a-zA-Z][a-zA-Z0-9\-_]";
                string rightExpressioPattern = string.Format(@"\${0}+(\.{0}*(\(.*\))*)*", IdetifierPattern);
                MatchCollection mc2 = Regex.Matches(lineText, rightExpressioPattern);
                if (mc2.Count > 0)
                {
                    ret = mc2[mc2.Count - 1].Value;
                }
            }
            catch
            { }
            return ret;
        }


		#region Error Overloads (Severity)
		public void ReportError(TextSpan location, string message)
		{
			ReportError(location, message, Severity.Error);
		}

		public void ReportFatal(TextSpan location, string message)
		{
			ReportError(location, message, Severity.Fatal);
		}

		public void ReportWarning(TextSpan location, string message)
		{
			ReportError(location, message, Severity.Warning);
		}

		public void ReportHint(TextSpan location, string message)
		{
			ReportError(location, message, Severity.Hint);
		}
		#endregion

		#region TextSpan Conversion
		public TextSpan TextSpan(int startLine, int startIndex, int endIndex)
		{
			return TextSpan(startLine, startIndex, startLine, endIndex);
		}

		public TextSpan TextSpan(int startLine, int startIndex, int endLine, int endIndex)
		{
			TextSpan ts;
			ts.iStartLine = startLine - 1;
			ts.iStartIndex = startIndex;
			ts.iEndLine = endLine - 1;
			ts.iEndIndex = endIndex;
			return ts;
		}
		#endregion
	}
}